<template>
  <div class="home">
    <p>姓名 : {{ name }}</p>
    <button @click="fn1">fn1</button>
    <p>用户:{{ user }}</p>
    <button @click="setUser">setUser</button>

    <p>学生:{{ student }}</p>
    <button @click="setStu">setStu</button>
    <p>数组:{{ arr }}</p>
    <button @click="setArr">setArr</button>

    <hr />
    <!-- 子组件toRef-toRefs -->
    <to-ref-to-refs :a="100" :b="200" m="abc" n="edf" @setData="receiveData">
      <a href="#">插槽内容</a>
    </to-ref-to-refs>
    <p>父组件接收传值:{{ sonData }}</p>
    <hr />
    <readonly>
    </readonly>
  </div>
</template>

<script>
import { ref, reactive } from "vue";
import ToRefToRefs from "@/components/01-响应式工具-toRef-toRefs.vue";
import Readonly from "@/components/02-readonly.vue";
export default {
  name: "HomeView",
  components: {
    ToRefToRefs,
    Readonly,
  },
  setup() {
    // 1. setup 不能用async修饰，因为返回值变成了promise
    // 2. 该函数在beforeCreate之前执行，执行时机更早

    // ref() =>RefImpl:声明基本数据类型的响应式数据
    const name = ref("wxr");
    let fn1 = () => {
      console.log(name);
      name.value = "张杰"; // 修改ref响应式数据(RefImpl),使用.value
    };
    let user = ref({
      hobby: "写写字",
      like: "水果茶",
    });
    let setUser = () => {
      console.log(user);
      user.value.like = "喜欢火龙果"; // 这个写法很不自然
    };

    // ref():声明响应式数据，一般用作基本数据类型的声明，引用数组和对象这两类型也能使用，不管是那种类型的数据，都必须使用.value修改数据，对于对象/数组类型来说，不是特别方便(一般修改属性是：对象.属性名，这个需要对象.value.属性名)。但是使用reactive()来声明引用对象/数组类型的响应式数据。

    // reactive() => Proxy: 声明引用类型的响应式数据. 返回值是Proxy代理对象, 也是vue3中实现数据响应式的核心用法. 而vue2中实现数据响应式的是Object.defineProperty()
    const student = reactive({
      motto: "要争气，因为有太多的不服气",
    });
    let setStu = () => {
      console.log(student);
      student.motto = "走自己的路，让别人说去吧";
      student.address = "郑州市高新区"; // 动态新增属性
      delete student.motto; // 动态删除属性
    };
    const arr = reactive([1, 2, 3]);
    const setArr = () => {
      console.log(arr); // 返回的是Proxy
      arr.push("88", "99");
    };

    /* 子传父 */
    let sonData = reactive({
      data: {},
    });
    console.log("----", sonData);

    const receiveData = (data) => {
      console.log("子传父:", data); // 此时，父组件已经接收到子组件传过来的值，但是父组件需要存起来，怎么存呢
      // sonData = data; // 修改了sonData 的指向，原来是一个Proxy对象，现在是普通的JS对象，数据的响应性丢失了
      // console.log("2....", sonData);
      sonData.data = data; // 要修改对象里面的属性！保持了sonData的数据响应
    };

    // 3. setup内部声明的数据和函数, 想在组件模板中使用, 一定记得return
    return {
      name,
      fn1,
      user,
      setUser,

      student,
      setStu,
      arr,
      setArr,

      receiveData,

      sonData,
    };
  },
};
</script>
